/** @file    MethodArguments.cpp
 *  @author  Alessandro Polo
 *  @version $Id: MethodArguments.cpp 2827 2010-08-02 11:01:48Z alex $
 *  @brief
 * File containing methods for the wosh::MethodArguments class.
 * The header for this class can be found in MethodArguments.h, check that file
 * for class description.
 ****************************************************************************/
/* Copyright (c) 2007-2010, WOSH - Wide Open Smart Home 
 * by Alessandro Polo - OpenSmartHome.com
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the OpenSmartHome.com WOSH nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY Alessandro Polo ''AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL Alessandro Polo BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 ****************************************************************************/

 #include <core/MethodArguments.h>

 #include <core/ObjectAllocator.h>


using namespace std;
namespace wosh {

 WOSH_REGISTER(wosh::MethodArgument, "", 1.00, _static_MethodArgument )
 WOSH_REGISTER(wosh::MethodArguments, "", 1.00, _static_MethodArguments )

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////

void MethodArgument::set( Variant::DATA_TYPE type, bool is_optional, int index ) {
	this->typeName = Utilities::format("%s::%s", Variant::className(), Variant::getTypeAsString(type));
	this->optional = is_optional;
	this->ordered = index;
 }

void MethodArgument::set( const char* classname, bool is_optional, int index ) {
	this->typeName.assign(classname);
	this->optional = is_optional;
	this->ordered = index;
 }

MethodArgument& MethodArgument::operator=(const MethodArgument& m) {
	this->typeName = m.typeName;
	this->optional = m.optional;
	this->ordered = m.ordered;
	return *this;
 }

bool MethodArgument::operator==(const MethodArgument &other) const {
	if ( this->typeName != other.typeName )
		return false;
	if ( this->optional != other.optional )
		return false;
	if ( this->ordered != other.ordered )
		return false;
	return true;
 }

bool MethodArgument::operator>(const MethodArgument& other) const {
	if ( this->ordered > other.ordered )
		return true;
	if ( this->typeName > other.typeName )
		return true;
	if ( this->optional > other.optional )
		return true;
	if ( this->ordered < other.ordered )
		return false;
	if ( this->optional < other.optional )
		return false;
	return true;
 }

bool MethodArgument::operator<(const MethodArgument& other) const {
	if ( this->ordered < other.ordered )
		return true;
	if ( this->typeName < other.typeName )
		return true;
	if ( this->optional < other.optional )
		return true;
	return false;
 }

std::string MethodArgument::toString() const {
	std::string res = "";
	if ( this->typeName.empty() )
		res = "[]";
	else
		res = "[" + this->typeName + "]";
	if ( optional )
		res = "(o)";
	return res;
 }

bool MethodArgument::updateHash( DataHashContext* hash_context ) const {
	if ( hash_context == NULL ) return false;
	bool ret = true;
	ret = hash_context->update( this->typeName ) & ret;
	ret = hash_context->update( this->optional ) & ret;
	ret = hash_context->update( this->ordered ) & ret;
	ret = hash_context->update( this->fieldName ) & ret;
	return ret;
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////

MethodArguments& MethodArguments::operator=(const MethodArguments& m) {
	this->args.clear();
	std::vector<MethodArgument>::const_iterator it;
	for(it=m.args.begin(); it!=m.args.end(); ++it) {
		this->args.push_back(*it);
	 }
	return *this;
 }

bool MethodArguments::operator==(const MethodArguments &other) const {
	if ( this->args.size() != other.args.size() )
		return false;

	return true;
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////

std::string MethodArguments::toString() const {
	std::string ret = "";
	std::vector<MethodArgument>::const_iterator it;
	for(it=this->args.begin(); it!=this->args.end(); ++it) {
		ret += (*it).toString() + "; ";
	 }
	return ret;
 }

bool MethodArguments::updateHash( DataHashContext* hash_context ) const {
	if ( hash_context == NULL ) return false;
	bool ret = true;
	std::vector<MethodArgument>::const_iterator it;
	for(it=this->args.begin(); it!=this->args.end(); ++it) {
		ret = (*it).updateHash(hash_context) & ret;
	 }
	return ret;
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////

}; // namespace wosh
